namespace ScrumSprintMonitor.TestbenchApp.Views.TestbenchView
{
	#region #using Directives

	using System;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Linq;
	using System.Windows;
	using System.Windows.Input;

	using Microsoft.Practices.Composite.Presentation.Commands;

	using ScrumSprintMonitor.Infrastructure;

	using Testbench.Impl;

	#endregion

	internal class TestbenchViewModel : ITestbenchViewModel
	{
		private readonly DelegateCommand<Window> closeCommand;
		private readonly IReportableData reportableData;
		private readonly ITeamMemberInfoProvider teamMemberInfoProvider;
		private readonly BindingList<IWorkItemAdapter> workItems;
		private string currentCommiter;

		public TestbenchViewModel(IReportableData reportableData, IWorkItemStore workItemStore, ITeamMemberInfoProvider teamMemberInfoProvider)
		{
			this.closeCommand = new DelegateCommand<Window>(Close, CanClose);

			this.reportableData = reportableData;
			this.teamMemberInfoProvider = teamMemberInfoProvider;
			if (this.teamMemberInfoProvider.TeamMembers.Any())
			{
				this.currentCommiter = this.teamMemberInfoProvider.TeamMembers.First().Name;
			}

			this.workItems = workItemStore.WorkItems;
			this.workItems.ListChanged += workItems_ListChanged;
		}

		#region Implementation of ITestbenchViewModel

		public BuildStatus CurrentBuildStatus
		{
			get { return this.reportableData.LastBuild.Status; }
			set
			{
				if (value != this.reportableData.LastBuild.Status)
				{
					((TestBuildInfo) this.reportableData.LastBuild).Status = value;
					((TestBuildInfo) this.reportableData.LastBuild).FinishTime = SystemTime.Now();

					OnPropertyChanged("CurrentBuildStatus");
				}
			}
		}

		public IList<BuildStatus> AvailableBuildStatus
		{
			get
			{
				var values = new List<BuildStatus>();

				foreach (var value in Enum.GetValues(typeof(BuildStatus)))
				{
					values.Add((BuildStatus) value);
				}

				return values;
			}
		}

		public IBindingList WorkItems
		{
			get { return this.workItems; }
		}

		public IList<WorkItemState> ValidWorkItemStates
		{
			get
			{
				var values = new List<WorkItemState>();

				foreach (var value in Enum.GetValues(typeof(WorkItemState)))
				{
					values.Add((WorkItemState) value);
				}

				return values;
			}
		}

		public string CurrentCommiter
		{
			get { return this.currentCommiter; }
			set
			{
				if (value != this.currentCommiter)
				{
					this.currentCommiter = value;

					OnPropertyChanged("CurrentCommiter");
				}
			}
		}

		public IList<string> ValidTeamMembers
		{
			get { return this.teamMemberInfoProvider.TeamMembers.Select(x => x.Name).ToList(); }
		}

		public ICommand CloseCommand
		{
			get { return this.closeCommand; }
		}

		#endregion

		private static bool CanClose(Window window)
		{
			return true;
		}

		private static void Close(Window window)
		{
			window.Close();
		}

		private void workItems_ListChanged(object sender, ListChangedEventArgs e)
		{
			WritableWorkItem workItem = null;

			switch (e.ListChangedType)
			{
				case ListChangedType.ItemAdded:
				case ListChangedType.ItemChanged:
					workItem = (WritableWorkItem) this.workItems[e.NewIndex];
					break;
			}

			if (workItem != null)
			{
				workItem.ChangedBy = CurrentCommiter;
			}
		}

		#region INotifyPropertyChanged members

		public event PropertyChangedEventHandler PropertyChanged;

		private void OnPropertyChanged(string propertyName)
		{
			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
			}
		}

		#endregion
	}
}